package com.atguigu.gulimall.product.service.impl;

import com.atguigu.common.exception.BizException;
import com.atguigu.common.to.MemberPrice;
import com.atguigu.common.to.SkuReductionTo;
import com.atguigu.common.to.SpuBoundsTo;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.dao.SpuInfoDao;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.feign.CouponFeignService;
import com.atguigu.gulimall.product.service.*;
import com.atguigu.gulimall.product.vo.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    private SpuInfoDescService spuInfoDescService;

    private SpuImagesService spuImagesService;

    private ProductAttrValueService productAttrValueService;

    private AttrService attrService;

    private SkuInfoService skuInfoService;

    private SkuImagesService skuImagesService;

    private SkuSaleAttrValueService skuSaleAttrValueService;

    private CouponFeignService couponFeignService;

    @Autowired
    public SpuInfoServiceImpl(SpuInfoDescService spuInfoDescService,
                              SpuImagesService spuImagesService,
                              ProductAttrValueService productAttrValueService,
                              AttrService attrService,
                              SkuInfoService skuInfoService,
                              SkuImagesService skuImagesService,
                              SkuSaleAttrValueService skuSaleAttrValueService,
                              CouponFeignService couponFeignService) {
        this.spuInfoDescService = spuInfoDescService;
        this.spuImagesService = spuImagesService;
        this.productAttrValueService = productAttrValueService;
        this.attrService = attrService;
        this.skuInfoService = skuInfoService;
        this.skuImagesService = skuImagesService;
        this.skuSaleAttrValueService = skuSaleAttrValueService;
        this.couponFeignService = couponFeignService;
    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        LambdaQueryWrapper<SpuInfoEntity> wrapper = Wrappers.lambdaQuery();
        String status = (String) params.get("status");
        if (StringUtils.isNotBlank(status)) {
            wrapper.eq(SpuInfoEntity::getPublishStatus, status);
        }
        String brandId = (String) params.get("brandId");
        if (StringUtils.isNotBlank(brandId)) {
            wrapper.eq(SpuInfoEntity::getBrandId, brandId);
        }
        String catalogId = (String) params.get("catelogId");
        if (StringUtils.isNotBlank(catalogId)) {
            wrapper.eq(SpuInfoEntity::getCatalogId, catalogId);
        }
        String key = (String) params.get("key");
        if (StringUtils.isNotBlank(key)) {
            wrapper.and(w -> {
                w.eq(SpuInfoEntity::getId, key).or().like(SpuInfoEntity::getSpuName, key);
            });
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    /**
     * TODO 使用分布式事务
     *
     * @param vo
     */
    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void saveSpuInfo(SpuSaveVO vo) {
        // 1. 保存spu基本信息 pms_spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(vo, spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        this.save(spuInfoEntity);
        Long spuId = spuInfoEntity.getId();

        // 2. 保存spu的描述图片 pms_spu_info_desc
        List<String> decripts = vo.getDecript();
        SpuInfoDescEntity descEntity = new SpuInfoDescEntity();
        descEntity.setSpuId(spuId);
        descEntity.setDecript(String.join(",", decripts));
        spuInfoDescService.save(descEntity);

        // 3. 保存spu的图片集 pms_spu_images
        List<String> images = vo.getImages();
        List<SpuImagesEntity> spuImagesEntities = images.stream()
                .map(image -> {
                    SpuImagesEntity spuImagesEntity = new SpuImagesEntity();
                    spuImagesEntity.setSpuId(spuId);
                    spuImagesEntity.setImgUrl(image);
                    return spuImagesEntity;
                })
                .collect(Collectors.toList());
        spuImagesService.saveBatch(spuImagesEntities);

        // 4. 保存spu的规格参数 pms_product_attr_value
        List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
        List<Long> attrIds = baseAttrs.stream().map(BaseAttrs::getAttrId).collect(Collectors.toList());
        Collection<AttrEntity> attrEntities = attrService.listByIds(attrIds);
        // key -> attrId, value -> attrName
        Map<Long, String> attrIdNameMap = attrEntities.stream()
                .collect(Collectors.toMap(AttrEntity::getAttrId, AttrEntity::getAttrName));
        List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream()
                .map(baseAttr -> {
                    ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
                    productAttrValueEntity.setSpuId(spuId);
                    productAttrValueEntity.setAttrId(baseAttr.getAttrId());
                    productAttrValueEntity.setAttrValue(baseAttr.getAttrValues());
                    productAttrValueEntity.setAttrName(attrIdNameMap.get(baseAttr.getAttrId()));
                    productAttrValueEntity.setQuickShow(baseAttr.getShowDesc());
                    return productAttrValueEntity;
                }).collect(Collectors.toList());
        productAttrValueService.saveBatch(productAttrValueEntities);

        // 5. 保存spu积分信息 gulimall_sms -> sms_spu_bounds
        Bounds bounds = vo.getBounds();
        SpuBoundsTo spuBoundsTo = new SpuBoundsTo();
        BeanUtils.copyProperties(bounds, spuBoundsTo);
        spuBoundsTo.setSpuId(spuId);
        R resultOfSaveSpuBounds = couponFeignService.saveSpuBounds(spuBoundsTo);
        if (!resultOfSaveSpuBounds.getCode().equals(0)) {
            throw new BizException("远程调用 gulimall-coupon 保存 spu 积分信息失败! " + resultOfSaveSpuBounds);
        }
        // 6. 保存当前spu对应的所有sku信息
        List<Skus> skus = vo.getSkus();
        // 6.1 保存sku基本信息 pms_sku_info
        List<SkuInfoEntity> skuInfoEntities = new ArrayList<>();
        List<Map<String, Object>> skuMaps = skus.stream()
                .map(sku -> {
                    Map<String, Object> skusMap = new HashMap<>();
                    SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                    BeanUtils.copyProperties(sku, skuInfoEntity);
                    skuInfoEntity.setSpuId(spuId);
                    skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
                    skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
                    skuInfoEntity.setSaleCount(0L);
                    List<Images> imagesList = sku.getImages();
                    String skuDefaultImg = "";
                    for (Images image : imagesList) {
                        if (Integer.valueOf(1).equals(image.getDefaultImg())) {
                            skuDefaultImg = image.getImgUrl();
                            break;
                        }
                    }
                    skuInfoEntity.setSkuDefaultImg(skuDefaultImg);
                    skuInfoEntities.add(skuInfoEntity);
                    skusMap.put("sku", sku);
                    skusMap.put("skuInfoEntity", skuInfoEntity);
                    return skusMap;
                }).collect(Collectors.toList());
        skuInfoService.saveBatch(skuInfoEntities);


        // sku 图片信息
        List<SkuImagesEntity> allSkuImages = new ArrayList<>();
        // sku 销售属性
        List<SkuSaleAttrValueEntity> allSkuSaleAttrValues = new ArrayList<>();
        // sku
        List<SkuReductionTo> skuReductionTos = new ArrayList<>();
        for (Map<String, Object> skuMap : skuMaps) {
            Skus sku = (Skus) skuMap.get("sku");
            SkuInfoEntity skuInfoEntity = (SkuInfoEntity) skuMap.get("skuInfoEntity");
            List<Images> imagesList = sku.getImages();
            List<SkuImagesEntity> skuImagesEntities = imagesList.stream()
                    .map(image -> {
                        SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                        skuImagesEntity.setSkuId(skuInfoEntity.getSkuId());
                        skuImagesEntity.setImgUrl(image.getImgUrl());
                        skuImagesEntity.setDefaultImg(image.getDefaultImg());
                        return skuImagesEntity;
                    })
                    .filter(image -> StringUtils.isNotBlank(image.getImgUrl()))
                    .collect(Collectors.toList());
            allSkuImages.addAll(skuImagesEntities);
            List<Attr> attrs = sku.getAttr();
            List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attrs.stream()
                    .map(attr -> {
                        SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                        BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
                        skuSaleAttrValueEntity.setSkuId(skuInfoEntity.getSkuId());
                        return skuSaleAttrValueEntity;
                    }).collect(Collectors.toList());
            allSkuSaleAttrValues.addAll(skuSaleAttrValueEntities);
            SkuReductionTo skuReductionTo = new SkuReductionTo();
            BeanUtils.copyProperties(sku, skuReductionTo);

            // 过滤 skuReductionTo 会员价格为 0 的
            List<MemberPrice> memberPrices = sku.getMemberPrice().stream()
                    .map(memberPriceVo -> {
                        MemberPrice memberPriceTo = new MemberPrice();
                        BeanUtils.copyProperties(memberPriceVo, memberPriceTo);
                        return memberPriceTo;
                    })
                    .filter(memberPriceTo -> memberPriceTo.getPrice().compareTo(BigDecimal.ZERO) > 0)
                    .collect(Collectors.toList());
            skuReductionTo.setSkuId(skuInfoEntity.getSkuId());
            skuReductionTo.setMemberPrice(memberPrices);
            // 满减未设置都为 0 只添加满减数量 或者 满减价格大于0的 或者 有会员价格的
            if (skuReductionTo.getFullCount() > 0
                    || skuReductionTo.getFullPrice().compareTo(BigDecimal.ZERO) > 0
                    || !CollectionUtils.isEmpty(skuReductionTo.getMemberPrice())) {
                skuReductionTos.add(skuReductionTo);
            }
        }
        // 6.2 保存sku的图片信息 pms_sku_images
        skuImagesService.saveBatch(allSkuImages);
        // 6.3 保存sku的销售属性 pms_sku_sale_attr_value
        skuSaleAttrValueService.saveBatch(allSkuSaleAttrValues);
        // 6.4 保存sku的优惠满减信息 远程调用会员 coupon 模块 gulimall_sms -> sms_sku_ladder, sms_sku_full_reduction, sms_member_price
        R resultOfSaveSkuReductions = couponFeignService.saveSkuReductions(skuReductionTos);
        if (!resultOfSaveSkuReductions.getCode().equals(0)) {
            throw new BizException("远程调用 gulimall-coupon服务 保存 sku 优惠满减信息失败! " + resultOfSaveSkuReductions);
        }
    }

}
